package sy5_Structural_Pattern.decorator.decorator3;
/*
 * 考虑冰淇淋添加不同的口味，如饼干、蓝莓 和巧克力等。
 * 先前的项目设计，抽象装饰类定义了有参数的构造方法。
 * 本项目设计中，抽象装饰类没有定义有参的构造方法，而是对聚合的抽象构件对象定义setter方法，
 * 就可以灵活地嵌套和装饰已有对象。
 */

abstract class DQ{  //角色1：抽象构件，也可设计为接口。Dairy Queen（一种冰淋凌品牌——冰雪皇后）
	protected  abstract void  operation(); //抽象方法
}

class IceCream extends DQ{  //角色2：具体构件（被装饰类）
	@Override 
	public void operation() {
		System.out.print("DQ牌冰淇淋 ");
	}
}

abstract class Decorator extends DQ{  //角色3：抽象装饰类（核心类）
	private DQ component; //维护一个抽象构件（父类）对象
	
	public void setComponent(DQ component) {
		this.component = component;
	}
	
	@Override 
	public void operation() {
		if (component != null) {   //兼容最初的被装饰对象
			component.operation();
		}
	}
}

class Cookies extends Decorator{  //角色4：具体装饰类
	@Override 
	public void operation() {  //抽象方法在具体装饰类里被重写
		super.operation();   //调用基类方法
		System.out.print("，添加了饼干");  //装饰
	}
}

class BlueBerry extends Decorator {  //角色4：具体装饰类
	@Override
	public void operation() {  //抽象方法在具体装饰类里被重写
		super.operation();
		System.out.print("，添加了蓝莓 ");
	}
}

class ChocolateChip extends Decorator {  //角色4：具体装饰类
	@Override
	public void operation() {  //抽象方法在具体装饰类里被重写
		super.operation();
		System.out.print("，添加了巧克力 ");
	}
}

public class Client {  //客户端
	public static void main(String[] args) {
		DQ icecream = new IceCream();  //无参，被装饰对象
		Decorator cookies = new Cookies();  //无参，装饰对象
		Decorator blueBerry = new BlueBerry();  //无参，装饰对象
		Decorator chocolateChip = new ChocolateChip();  //无参，装饰对象
		//装饰动作
		cookies.setComponent(icecream);
		blueBerry.setComponent(cookies);
		chocolateChip.setComponent(blueBerry);
		//调用抽象方法，面对抽象编程
		chocolateChip.operation();
	}
}